home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / csrc1.arc / OBJREF.C < prev    next >
C/C++ Source or Header  |  1989-07-27  |  7KB  |  392 lines

  1.  
  2. /*
  3.  *             O B J R E F
  4.  *
  5.  * NOTE: this program has been superceded by additional capabilities in
  6.  * nm.c (in tools).  It is included here as it offers a simple set of
  7.  * subroutines for processing symbol tables.
  8.  */
  9.  
  10. /*)BUILD    $(TKBOPTIONS) = {
  11.             TASK    = ...REF
  12.         }
  13. */
  14.  
  15. #ifdef    DOCUMENTATION
  16.  
  17. title    objref    Object file cross reference
  18. index        Object file cross reference
  19.  
  20. synopsis
  21.  
  22.     objref file_list
  23.  
  24. description
  25.  
  26.     objref reads each file in the list, building a cross reference
  27.     listing of symbols (where symbols were defined and referenced).
  28.     .s
  29.     The files in the file_list were output by nm.  The file_list
  30.     arguments may contain wildcards.  The argument string to nm
  31.     is as follows:
  32.     .s
  33.         nm "-1" file.obj >file.nm
  34.  
  35. author
  36.  
  37.     Martin Minow
  38.  
  39. bugs
  40.  
  41.     Superceded by additional capabilities in nm.c
  42.  
  43. #endif
  44.  
  45. #include <stdio.h>
  46. #define    FALSE    0
  47. #define    TRUE    1
  48. #define    EOS    0
  49.  
  50. typedef struct symbol {
  51.     struct symbol    *s_next;
  52.     char        *s_name;
  53.     struct module    *s_defn;    /* Where it's defined        */
  54.     struct refer    *s_refer;    /* Where it's referenced    */
  55. } SYMBOL;
  56.  
  57. typedef struct module {
  58.     struct module    *m_next;
  59.     char        *m_name;
  60.     int        m_index;
  61. } MODULE;
  62.  
  63. typedef struct refer {
  64.     struct refer    *r_next;
  65.     struct module    *r_module;
  66. } REFERENCE;
  67.  
  68. SYMBOL        *sfirst        = NULL;
  69. MODULE        *mfirst        = NULL;
  70. REFERENCE    *rfirst        = NULL;
  71.  
  72. FILE        *fd;
  73. char        line[133];
  74. char        name[133];
  75. char        value[133];
  76. #define        CROSS_MAX    25
  77. int        cross[CROSS_MAX][CROSS_MAX];
  78. char        *mname[CROSS_MAX];
  79. int        cmax        = -1;
  80. extern char    *strsave();
  81. extern char    *myalloc();
  82.  
  83.  
  84. main(argc, argv)
  85. int        argc;
  86. char        *argv[];
  87. {
  88.     register int        nfiles;
  89.     register int        i;
  90.  
  91.     for (i = 1; i < argc; i++) {
  92.         if ((fd = fwild(argv[i], "r")) == NULL) {
  93.             fprintf(stderr, "can't open wild card file: ");
  94.             perror(argv[i]);
  95.             continue;
  96.         }
  97.         for (nfiles = 0; fnext(fd) != NULL; nfiles++) {
  98.             process();
  99.         }
  100.         if (nfiles == 0) {
  101.             fprintf(stderr, "no files match \"%s\"\n", argv[i]);
  102.         }
  103.     }
  104.     mnames();
  105.     output();
  106. }
  107.  
  108. process()
  109. /*
  110.  * For each file ...
  111.  */
  112. {
  113.     register MODULE        *mp;
  114.     register SYMBOL        *sy;
  115.     extern    MODULE        *newmodule();
  116.     extern    SYMBOL        *lookup();
  117.  
  118.     getfilename(fd, line);
  119.     mp = newmodule(line);
  120.     while (fgets(line, sizeof line, fd) != NULL) {
  121.         sscanf(line, "%s%*s%s", &name, &value);
  122.         sy = lookup(name);
  123.         if (value[0] == '*') {
  124.             addref(sy, mp);        /* Undefined here    */
  125.         }
  126.         else {                /* Defined here        */
  127.             if (sy->s_defn != NULL) {
  128.                 printf("** symbol %s defined in %s and %s\n",
  129.                     sy->s_name, (sy->s_defn)->m_name,
  130.                     mp->m_name);
  131.                 fprintf(stderr,
  132.                     "** symbol %s defined in %s and %s\n",
  133.                     sy->s_name, (sy->s_defn)->m_name,
  134.                     mp->m_name);
  135.             }
  136.             else {
  137.                 sy->s_defn = mp;
  138.             }
  139.         }
  140.     }
  141. }
  142.  
  143. output()
  144. {
  145.     register SYMBOL        *sy;
  146.     register int        nsy;
  147.     register REFERENCE    *rp;
  148.     int            i, j;
  149.  
  150.     /*
  151.      * Pass 1 for "library" symbols only
  152.      */
  153.     printf("The following are not defined:\n");
  154.     nsy = 0;
  155.     for (sy = sfirst; sy != NULL; sy = sy->s_next) {
  156.         if (sy->s_defn == NULL) {
  157.             printf("%c%s",
  158.                 ((nsy & 7) == 0) ? '\n' : '\t', sy->s_name);
  159.             nsy++;
  160.         }
  161.     }
  162.     printf("\n\n");
  163.     /*
  164.      * Pass 2 for symbols not used elsewhere
  165.      */
  166.     printf("The following are not used outside of their module:\n");
  167.     nsy = 0;
  168.     for (sy = sfirst; sy != NULL; sy = sy->s_next) {
  169.         if (sy->s_defn != NULL && sy->s_refer == NULL) {
  170.             printf("%c%s\t%s",
  171.                 ((nsy & 3) == 0) ? '\n' : '\t',
  172.                     sy->s_name, (sy->s_defn)->m_name);
  173.             nsy++;
  174.         }
  175.     }
  176.     /*
  177.      * Pass 3 -- all the rest
  178.      */
  179.     printf("\n\nThe following are defined and used elsewhere\n");
  180.     for (sy = sfirst; sy != NULL; sy = sy->s_next) {
  181.         if (sy->s_defn == NULL || sy->s_refer == NULL) {
  182.             continue;
  183.         }
  184.         i = (sy->s_defn)->m_index;
  185.         printf("\n%s\t%s:", sy->s_name, (sy->s_defn)->m_name);
  186.         nsy = 0;
  187.         for (rp = sy->s_refer; rp != NULL; rp = rp->r_next) {
  188.             printf("%s%s",
  189.                 ((++nsy % 6) == 0) ? "\n\t\t" : "\t",
  190.                 (rp->r_module)->m_name);
  191.             j = (rp->r_module)->m_index;
  192.             cross[i][j]++;
  193.         }
  194.     }
  195.     printf("\n");
  196.     /*
  197.      * Now for the map
  198.      */
  199.     printf("\nmodule");
  200.     for (i = 0; i <= cmax; i++) {
  201.         printf("\n%s\t", mname[i]);
  202.         for (j = 0; j < i; j++) {
  203.             printf("%4d", cross[i][j] + cross[j][i]);
  204.         }
  205.         printf("   %s", mname[i]);
  206.     }
  207. }
  208.  
  209. /*
  210.  * Manage symbol table
  211.  */
  212. MODULE *
  213. newmodule(text)
  214. /*
  215.  * Make this a new module entry.
  216.  */
  217. {
  218.     register MODULE        *mp;
  219.     register MODULE        **mplast;
  220.     register MODULE        *new;
  221.     int            i;
  222.  
  223.     new = myalloc(sizeof (MODULE));
  224.     new->m_name = strsave(text);
  225.     for (mplast = &mfirst; (mp = *mplast) != NULL; mplast = &mp->m_next) {
  226.         if ((i = strcmp(text, mp->m_name)) < 0)
  227.             break;
  228.         else if (i == 0) {
  229.             fprintf(stderr, "duplicate module name \"%s\"\n",
  230.                 text);
  231.             return(mp);
  232.         }
  233.     }
  234.     new->m_next = mp;
  235.     *mplast = new;
  236.     cmax++;
  237.     if (cmax >= CROSS_MAX)
  238.         error("too many modules");
  239.     return(new);
  240. }
  241.  
  242. addref(sy, mp)
  243. SYMBOL        *sy;
  244. MODULE        *mp;
  245. /*
  246.  * The module references this symbol.
  247.  */
  248. {
  249.     register REFERENCE    *rp;
  250.      REFERENCE        **rplast;
  251.     register REFERENCE    *new;
  252.     register int        i;
  253.  
  254.     new = myalloc(sizeof (REFERENCE));
  255.     new->r_module = mp;
  256.     for (rplast = &sy->s_refer;
  257.             (rp = *rplast) != NULL;
  258.             rplast = &rp->r_next) {
  259.         if ((i = strcmp(mp->m_name, (rp->r_module)->m_name)) == 0) {
  260.             fprintf(stderr, "\"%s\" references \"%s\" twice\n",
  261.                 sy->s_name, mp->m_name);
  262.         }
  263.         else if (i < 0) {
  264.             break;
  265.         }
  266.     }
  267.     new->r_next = rp;
  268.     *rplast = new;
  269. }
  270.  
  271. SYMBOL *
  272. lookup(text)
  273. char        *text;
  274. /*
  275.  * Return pointer to this symbol, insert if new
  276.  */
  277. {
  278.     register SYMBOL        *sy;
  279.      SYMBOL            **sylast;
  280.     register SYMBOL        *new;
  281.     register int        i;
  282.  
  283.     for (sylast = &sfirst; (sy = *sylast) != NULL; sylast = &sy->s_next) {
  284.         if ((i = strcmp(text, sy->s_name)) == 0) {
  285.             return(sy);
  286.         }
  287.         else if (i < 0) {
  288.             break;
  289.         }
  290.     }
  291.     new = myalloc(sizeof (SYMBOL));
  292.     new->s_name = strsave(text);
  293.     new->s_next = sy;
  294.     *sylast = new;
  295.     return (new);
  296. }
  297.  
  298. mnames()
  299. /*
  300.  * Build mname[] vector
  301.  */
  302. {
  303.     register int        i;
  304.     register MODULE        *mp;
  305.  
  306.     i = 0;
  307.     for (mp = mfirst; mp != NULL; mp = mp->m_next, i++) {
  308.         mname[i] = mp->m_name;
  309.         mp->m_index = i;
  310.     }
  311. }
  312.  
  313. /*
  314.  * Support routines
  315.  */
  316. getfilename(filedes, buffer)
  317. FILE    *filedes;
  318. char    *buffer;
  319. {
  320.     register char *tp;
  321.     register char c;
  322.  
  323.     fgetname(filedes, buffer);
  324.     /*
  325.      * Skip over device name
  326.      */
  327.     for (tp = buffer; (c = *tp) != EOS && c != ':'; tp++);
  328.     if (c)    tp++;
  329.     else    tp = buffer;
  330.     /*
  331.      * Skip over [UIC] or
  332.      * or [PPN] if present
  333.      */
  334.     if (*tp == '[' || *tp == '(') {
  335.         while ((c = *tp++)
  336.                 && c != ']'
  337.                 && c != ')');
  338.         if (c == 0) {
  339.             error("Can't happen");
  340.             tp--;
  341.         }
  342.     }
  343.     strcpy(buffer, tp);
  344.     /*
  345.      * Don't include version
  346.      */
  347.     for (tp = buffer; (c = *tp) && c != ';'; tp++);
  348.     *tp = 0;
  349.     /*
  350.      * Don't include .ext
  351.      */
  352.     for (tp = buffer; (c = *tp) && c != '.'; tp++);
  353.     *tp = 0;
  354.     /*
  355.      * Now, buffer has the file name,
  356.      * tp - buffer, its length.
  357.      */
  358.     return(buffer);
  359. }
  360.  
  361. char *
  362. strsave(text)
  363. char        *text;
  364. /*
  365.  * Save this text
  366.  */
  367. {
  368.     register char    *p;
  369.  
  370.     if ((p = malloc(strlen(text) + 1)) == NULL)
  371.         error("No room for string alloc.");
  372.     strcpy(p, text);
  373.     return (p);
  374. }
  375.  
  376. char *
  377. myalloc(size)
  378. int        size;
  379. /*
  380.  * Allocate or die
  381.  */
  382. {
  383.     register char    *p;
  384.  
  385.     if ((p = calloc(1, size)) == NULL) {
  386.         fprintf(stderr, "Can't allocate %d bytes\n", size);
  387.         error("Fatal");
  388.     }
  389.     return (p);
  390. }
  391.  
  392.